﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using ManagementTool.ESB;
using ManagementTool.LogServiceReference;
using SpringEngine;
using Point = System.Windows.Point;

namespace ManagementTool
{
    public partial class MainPage : UserControl
    {
        private SpringEngine.SpringEngine springEngine;
        private ExposeServiceBusClient esbClient;

        List<ServiceUserControl> services = new List<ServiceUserControl>();
        public MainPage()
        {
            InitializeComponent();
            //
            springEngine = new SpringEngine.SpringEngine();
            springEngine.OnVectorsCalculated += new SpringEngine.SpringEngine.VectorsCalculated(springEngine_OnVectorsCalculated);
            springEngine.Start();
            EstablishLogConnection();
            //
            EstablishEsbConnection();
            esbClient.GetServicesCompleted +=
                new EventHandler<GetServicesCompletedEventArgs>(esbClient_GetServicesCompleted);
            esbClient.GetServicesAsync();
        }

        private void EstablishLogConnection()
        {
            EndpointAddress address = new EndpointAddress("http://localhost:9953/Endpoint/");
            PollingDuplexHttpBinding binding = new PollingDuplexHttpBinding(PollingDuplexMode.SingleMessagePerPoll);

            proxy = new ManagementEndpointClient(binding, address);
            proxy.SendLogReceived += new EventHandler<SendLogReceivedEventArgs>(proxy_SendLogReceived);
            proxy.EstablishConnectionAsync();
        }

        private void EstablishEsbConnection()
        {
            EndpointAddress address = new EndpointAddress("http://localhost:5678/Router/");
            PollingDuplexHttpBinding binding = new PollingDuplexHttpBinding(PollingDuplexMode.SingleMessagePerPoll);

            esbClient = new ExposeServiceBusClient(binding, address);
            esbClient.ServiceAppearedReceived += new EventHandler<ServiceAppearedReceivedEventArgs>(esbClient_ServiceAppearedReceived);
            esbClient.ServiceDisappearedReceived += new EventHandler<ServiceDisappearedReceivedEventArgs>(esbClient_ServiceDisappearedReceived);
            //
            esbClient.GetRoutedServicesCompleted += new EventHandler<GetRoutedServicesCompletedEventArgs>(client_GetRoutedServicesCompleted);
            esbClient.GetAllServicesCompleted += new EventHandler<GetAllServicesCompletedEventArgs>(client_GetAllServicesCompleted); 
            //
            esbClient.EstablishConnectionAsync();
        }

        void esbClient_ServiceDisappearedReceived(object sender, ServiceDisappearedReceivedEventArgs e)
        {
            RemoveService(e.service);
        }

        void esbClient_ServiceAppearedReceived(object sender, ServiceAppearedReceivedEventArgs e)
        {
            AddService(e.service);
        }

        void esbClient_GetServicesCompleted(object sender, GetServicesCompletedEventArgs e)
        {
            foreach (ESB.Service service in e.Result)
            {
                AddService(service);
            }
        }

        void springEngine_OnVectorsCalculated(IEnumerable<Endpoint> endpoints)
        {
            if (isDrag)
            {
                service_MouseMove(null, lastMouseEventArgs);
            }
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            ESB.ExposeServiceBusClient client = new ExposeServiceBusClient();
            client.GetServicesAsync();
        }

        Random rand = new Random();

        private ManagementEndpointClient proxy;

        private void uxBindToServices_Click(object sender, RoutedEventArgs e)
        {
            EstablishLogConnection();
            EstablishEsbConnection();
        }

        void proxy_SendLogReceived(object sender, SendLogReceivedEventArgs e)
        {
            listBox1.Items.Add(String.Format("[{0}] [{1}] [{2}] {3}", e.log.TimeStamp, e.log.LoggerName, e.log.Level, e.log.Message));
            BlinkService(e.log.LoggerName);
        }

        private void BlinkService(string loggerName)
        {
            var logService = from child in uxServiceCanvas.Children
                                   where child is ServiceUserControl &&
                                         (((ServiceUserControl)child).Service.Name == "LogReceiverServer" ||
                                          ((ServiceUserControl)child).Service.Name == "ILogReceiverServer")
                                   select child;
            if (logService.Count() == 1)
            {
                ServiceUserControl service = (ServiceUserControl)logService.First();

                service.BlinkAnimation.Begin();
            }


            if (loggerName == "ESB")
            {
                uxESB.BlinkAnimation.Begin();
            }
            else
            {
                var matchingServices = from child in uxServiceCanvas.Children
                                       where child is ServiceUserControl &&
                                             (((ServiceUserControl) child).Service.Name == loggerName ||
                                              ((ServiceUserControl) child).Service.Name == "I" + loggerName) ||
                                              ((ServiceUserControl)child).Text == loggerName
                                       select child;

                if (matchingServices.Count() == 1)
                {
                    ServiceUserControl service = (ServiceUserControl) matchingServices.First();

                    service.BlinkAnimation.Begin();
                }
            }
        }

        //private void AddService(ManagmentLog e)
        //{
        //    Service service = new Service() { Width = 125, Height = 125, Text = e.Message };
        //    service.MouseMove += new MouseEventHandler(service_MouseMove);
        //    service.MouseLeftButtonDown += new MouseButtonEventHandler(service_MouseLeftButtonDown);
        //    service.MouseLeftButtonUp += new MouseButtonEventHandler(service_MouseLeftButtonUp);
        //    Canvas.SetLeft(service, uxServiceCanvas.ActualWidth / 2 + rand.NextDouble());
        //    Canvas.SetTop(service, uxServiceCanvas.ActualHeight / 2 + rand.NextDouble());
        //    services.Add(service);
        //    uxServiceCanvas.Children.Add(service);

        //    if (services.Count > 1)
        //        foreach (Service s in services)
        //            springEngine.AddSpring(new Spring(s, service, 300));
        //}

        private void AddService(ManagementTool.ESB.Service esbService)
        {
            ServiceUserControl service = new ServiceUserControl(esbService, esbClient) { Width = 125, Height = 125 };
            service.MouseMove += new MouseEventHandler(service_MouseMove);
            service.MouseLeftButtonDown += new MouseButtonEventHandler(service_MouseLeftButtonDown);
            service.MouseLeftButtonUp += new MouseButtonEventHandler(service_MouseLeftButtonUp);
            Canvas.SetLeft(service, uxServiceCanvas.ActualWidth / 2 + rand.NextDouble());
            Canvas.SetTop(service, uxServiceCanvas.ActualHeight / 2 + rand.NextDouble());
            services.Add(service);
            uxServiceCanvas.Children.Add(service);

            if (services.Count > 1)
                foreach (ServiceUserControl s in services)
                    springEngine.AddSpring(new Spring(s, service, 300));
        }

        private void RemoveService(ManagementTool.ESB.Service esbService)
        {
            var service = services.First(s => s.Service.Name == esbService.Name);
            uxServiceCanvas.Children.Remove(service);
            springEngine.RemoveEndpoint(service);
            services.Remove(service);
        }

        private bool isDrag = false;
        private ServiceUserControl draggingService;
        private MouseEventArgs lastMouseEventArgs;

        private void service_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            isDrag = true;
            draggingService = (ServiceUserControl)sender;
            Canvas.SetZIndex(draggingService, 1000);
        }

        private void service_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            isDrag = false;
            Canvas.SetZIndex(draggingService, 100);
        }

        private void service_MouseMove(object sender, MouseEventArgs e)
        {
            if (isDrag)
            {
                lastMouseEventArgs = e;
                try //eliminate exception if there is no Endpoints
                {
                    springEngine.Endpoints.First(p => p.EndpointObject == draggingService).Position =
                        new SpringEngine.Point(
                            e.GetPosition(uxServiceCanvas).X,
                            e.GetPosition(uxServiceCanvas).Y
                            );
                }
                catch (Exception) { }
            }
        }

        private void uxServiceRepositoryTab_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            esbClient.GetAllServicesAsync();
            esbClient.GetRoutedServicesAsync();
        }

        void client_GetAllServicesCompleted(object sender, GetAllServicesCompletedEventArgs e)
        {
            uxRepositoryAllServices.Items.Clear();
            foreach (ESB.Service service in e.Result)
            {
                uxRepositoryAllServices.Items.Add(new RepositoryService(service,esbClient));
            }
        }

        void client_GetRoutedServicesCompleted(object sender, GetRoutedServicesCompletedEventArgs e)
        {
            uxRepositoryRoutedServices.Items.Clear();
            foreach (ESB.Service service in e.Result)
            {
                uxRepositoryRoutedServices.Items.Add(new RepositoryService(service,esbClient));
            }
        }

        private void tabControl1_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

        }

    }
}
